#include "../src/lib/crypto.h"
#include <stdio.h>
#include <string.h>

void print_hex(const char *label, const uint8_t *data, size_t len) {
    printf("%s: ", label);
    for (size_t i = 0; i < len; i++) {
        printf("%02x", data[i]);
    }
    printf("\n");
}

void demo_sha256() {
    printf("\n=== SHA256 哈希演示 ===\n");
    
    const char *message = "Hello, World!";
    uint8_t digest[SHA256_DIGEST_SIZE];
    
    int ret = sha256_hash((const uint8_t *)message, strlen(message), digest);
    if (ret == CRYPTO_SUCCESS) {
        print_hex("消息", (const uint8_t *)message, strlen(message));
        print_hex("SHA256哈希", digest, SHA256_DIGEST_SIZE);
    } else {
        printf("SHA256哈希计算失败\n");
    }
}

void demo_aes() {
    printf("\n=== AES 加密演示 ===\n");
    
    // 生成随机密钥和IV
    uint8_t key[AES_KEY_SIZE_256];
    uint8_t iv[AES_BLOCK_SIZE];
    uint8_t salt[16];
    
    crypto_random_bytes(key, AES_KEY_SIZE_256);
    crypto_generate_iv(iv, AES_BLOCK_SIZE);
    crypto_generate_salt(salt, 16);
    
    print_hex("AES密钥", key, AES_KEY_SIZE_256);
    print_hex("IV", iv, AES_BLOCK_SIZE);
    print_hex("盐值", salt, 16);
    
    // 准备明文（需要是16字节的倍数）
    const char *plaintext = "This is a test message for AES encryption!";
    size_t plaintext_len = strlen(plaintext);
    size_t padded_len = ((plaintext_len + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
    
    uint8_t *ciphertext = malloc(padded_len);
    uint8_t *decrypted = malloc(padded_len);
    
    if (!ciphertext || !decrypted) {
        printf("内存分配失败\n");
        return;
    }
    
    // 填充明文
    memcpy(ciphertext, plaintext, plaintext_len);
    memset(ciphertext + plaintext_len, 0, padded_len - plaintext_len);
    
    // 初始化AES上下文
    aes_ctx_t aes_ctx;
    int ret = aes_init(&aes_ctx, key, AES_KEY_SIZE_256);
    if (ret != CRYPTO_SUCCESS) {
        printf("AES初始化失败\n");
        goto cleanup;
    }
    
    // CBC模式加密
    ret = aes_encrypt_cbc(&aes_ctx, ciphertext, padded_len, iv, ciphertext);
    if (ret == CRYPTO_SUCCESS) {
        print_hex("明文", (const uint8_t *)plaintext, plaintext_len);
        print_hex("密文", ciphertext, padded_len);
        
        // CBC模式解密
        ret = aes_decrypt_cbc(&aes_ctx, ciphertext, padded_len, iv, decrypted);
        if (ret == CRYPTO_SUCCESS) {
            print_hex("解密结果", decrypted, plaintext_len);
            if (memcmp(plaintext, decrypted, plaintext_len) == 0) {
                printf("AES加密/解密成功！\n");
            } else {
                printf("AES加密/解密失败\n");
            }
        }
    }
    
cleanup:
    free(ciphertext);
    free(decrypted);
}

void demo_rsa() {
    printf("\n=== RSA 加密演示 ===\n");
    
    // 生成RSA密钥对
    rsa_keypair_t keypair;
    int ret = rsa_generate_keypair(&keypair, RSA_KEY_SIZE_2048);
    if (ret != CRYPTO_SUCCESS) {
        printf("RSA密钥生成失败\n");
        return;
    }
    
    print_hex("RSA模数(n)", keypair.n, keypair.n_len);
    print_hex("RSA公钥指数(e)", keypair.e, keypair.e_len);
    print_hex("RSA私钥指数(d)", keypair.d, keypair.d_len);
    
    // 测试加密/解密
    const char *message = "Test";
    uint8_t ciphertext[4];
    uint8_t decrypted[4];
    
    ret = rsa_encrypt(&keypair, (const uint8_t *)message, 4, ciphertext);
    if (ret == CRYPTO_SUCCESS) {
        print_hex("明文", (const uint8_t *)message, 4);
        print_hex("密文", ciphertext, 4);
        
        ret = rsa_decrypt(&keypair, ciphertext, 4, decrypted);
        if (ret == CRYPTO_SUCCESS) {
            print_hex("解密结果", decrypted, 4);
            if (memcmp(message, decrypted, 4) == 0) {
                printf("RSA加密/解密成功！\n");
            }
        }
    }
    
    // 测试数字签名
    const char *data = "Hello, RSA signing!";
    uint8_t signature[SHA256_DIGEST_SIZE];
    
    ret = rsa_sign(&keypair, (const uint8_t *)data, strlen(data), signature);
    if (ret == CRYPTO_SUCCESS) {
        print_hex("签名数据", (const uint8_t *)data, strlen(data));
        print_hex("数字签名", signature, SHA256_DIGEST_SIZE);
        
        ret = rsa_verify(&keypair, (const uint8_t *)data, strlen(data), signature);
        if (ret == CRYPTO_SUCCESS) {
            printf("RSA签名验证成功！\n");
        } else {
            printf("RSA签名验证失败\n");
        }
    }
    
    rsa_free_keypair(&keypair);
}

void demo_pbkdf2() {
    printf("\n=== PBKDF2 密钥派生演示 ===\n");
    
    const char *password = "my_secret_password";
    uint8_t salt[16];
    uint8_t derived_key[32];
    
    crypto_generate_salt(salt, 16);
    
    int ret = pbkdf2_sha256((const uint8_t *)password, strlen(password),
                           salt, 16, 10000, derived_key, 32);
    if (ret == CRYPTO_SUCCESS) {
        print_hex("密码", (const uint8_t *)password, strlen(password));
        print_hex("盐值", salt, 16);
        print_hex("派生密钥", derived_key, 32);
        printf("PBKDF2密钥派生成功！\n");
    }
}

void demo_hmac() {
    printf("\n=== HMAC-SHA256 演示 ===\n");
    
    const char *key = "secret_key";
    const char *message = "Hello, HMAC!";
    uint8_t mac[SHA256_DIGEST_SIZE];
    
    int ret = hmac_sha256((const uint8_t *)key, strlen(key),
                         (const uint8_t *)message, strlen(message), mac);
    if (ret == CRYPTO_SUCCESS) {
        print_hex("密钥", (const uint8_t *)key, strlen(key));
        print_hex("消息", (const uint8_t *)message, strlen(message));
        print_hex("HMAC", mac, SHA256_DIGEST_SIZE);
        printf("HMAC-SHA256计算成功！\n");
    }
}

void demo_hex_conversion() {
    printf("\n=== 十六进制转换演示 ===\n");
    
    uint8_t original[] = {0x48, 0x65, 0x6c, 0x6c, 0x6f}; // "Hello"
    char hex[11];
    uint8_t converted[5];
    size_t converted_len;
    
    crypto_bytes_to_hex(original, 5, hex);
    printf("原始字节: ");
    print_hex("", original, 5);
    printf("十六进制字符串: %s\n", hex);
    
    int ret = crypto_hex_to_bytes(hex, converted, &converted_len);
    if (ret == CRYPTO_SUCCESS) {
        print_hex("转换回字节", converted, converted_len);
        if (memcmp(original, converted, 5) == 0) {
            printf("十六进制转换成功！\n");
        }
    }
}

int main() {
    printf("密码学算法库演示程序\n");
    printf("====================\n");
    
    demo_sha256();
    demo_aes();
    demo_rsa();
    demo_pbkdf2();
    demo_hmac();
    demo_hex_conversion();
    
    printf("\n演示完成！\n");
    return 0;
} 